home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
a_utils
/
_archvrs
/
unix
/
lha101u
/
src
/
lhext.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-23
|
7KB
|
359 lines
/*----------------------------------------------------------------------*/
/* LHarc Extract Command */
/* This is part of LHarc UNIX Archiver Driver */
/* */
/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */
/* */
/* V0.00 Original 1988.05.23 Y.Tagawa */
/* V1.00 Fixed 1989.09.22 Y.Tagawa */
/* V0.03 LHa for UNIX 1991.12.17 M.Oki */
/*----------------------------------------------------------------------*/
#include "lharc.h"
extern int decode_lzhuf ();
static boolean
inquire_extract (name)
char *name;
{
struct stat stbuf;
if (stat (name, &stbuf) >= 0)
{
if (!is_regularfile (&stbuf))
{
error ("Already exist (not a file)", name);
return FALSE;
}
if (noexec)
{
printf ("EXTRACT %s but file is exist.\n", name);
return FALSE;
}
else if (!force)
{
if (!isatty(0)) return FALSE;
switch (inquire ("OverWrite ?(Yes/No/All)", name, "YyNnAa"))
{
case 0:
case 1: /* Y/y */
break;
case 2:
case 3: /* N/n */
return FALSE;
case 4:
case 5: /* A/a */
force = TRUE;
break;
}
}
}
if (noexec)
printf ("EXTRACT %s\n", name);
return TRUE;
}
static boolean
make_parent_path (name)
char *name;
{
char path[FILENAME_LENGTH];
struct stat stbuf;
register char *p;
/* make parent directory name into PATH for recursive call */
strcpy (path, name);
for (p = path + strlen (path); p > path; p--)
if (p[-1] == '/')
{
*--p = '\0';
break;
}
if (p == path)
{
message ("Why?", "ROOT");
return FALSE; /* no more parent. */
}
if (stat (path, &stbuf) >= 0)
{
if (is_directory (&stbuf))
return TRUE;
error ("Not a directory", path);
return FALSE;
}
errno = 0;
if (verbose)
printf ("Making directory \"%s\".", path);
if (mkdir (path, 0777) >= 0)/* try */
return TRUE; /* successful done. */
errno = 0;
if (!make_parent_path (path))
return FALSE;
if (mkdir (path, 0777) < 0) /* try again */
{
message ("Cannot make directory", path);
return FALSE;
}
return TRUE;
}
static FILE *
open_with_make_path (name)
char *name;
{
FILE *fp;
if ((fp = fopen (name, WRITE_BINARY)) == NULL)
{
errno = 0;
if (!make_parent_path (name) ||
(fp = fopen (name, WRITE_BINARY)) == NULL)
error ("Cannot extract", name);
errno = 0;
}
return fp;
}
static void
adjust_info (name,hdr)
char *name;
LzHeader *hdr;
{
time_t utimebuf[2];
unsigned myuid;
/* adjust file stamp */
utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
utime (name, utimebuf);
if (hdr->extend_type == EXTEND_UNIX
|| hdr->extend_type == EXTEND_OS68K
|| hdr->extend_type == EXTEND_XOSK)
{
#if 0 /* GRR: chown(,-1,) is not valid argument */
if (!myuid)
chown (name, hdr->unix_uid, hdr->unix_gid);
else if (myuid == hdr->unix_uid)
chown (name, -1 , hdr->unix_gid);
#endif
if ((myuid = getuid()) == hdr->unix_uid || myuid == 0)
chown (name, hdr->unix_uid, hdr->unix_gid);
#ifdef NOT_COMPATIBLE_MODE
Please need your modification in this space.
#else
chmod (name, hdr->unix_mode); /* Do this after chown so suid stays */
#endif
errno = 0;
}
}
static char *methods[10] =
{
"-lh0-", "-lh1-", "-lh2-", "-lh3-", "-lh4-",
"-lh5-", "-lzs-", "-lz5-", "-lz4-", NULL
};
static void
extract_one (afp, hdr)
FILE *afp; /* archive file */
LzHeader *hdr;
{
FILE *fp; /* output file */
char name[257];
int crc;
int method;
boolean save_quiet, save_verbose;
char *q = hdr->name , c;
if ( ignore_directory && rindex(hdr->name,'/') )
{
q = (char *)rindex(hdr->name,'/') + 1;
}
else
{
if ( *q=='/' )
{
q++;
/*
* if OSK then strip device name
*/
if (hdr->extend_type == EXTEND_OS68K
|| hdr->extend_type == EXTEND_XOSK )
{
do c=(*q++); while ( c && c!='/' );
if ( !c || !*q ) q = "."; /* if device name only */
}
}
}
if (extract_directory)
sprintf (name, "%s/%s", extract_directory, q);
else
strcpy (name, q);
if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
{
for (method = 0; ; method++)
{
if (methods[method] == NULL)
{
error ("Unknown method skiped ...", name);
return;
}
if (bcmp (hdr->method, methods[method], 5) == 0)
break;
}
reading_filename = archive_name;
writting_filename = name;
if (output_to_stdout || verify_mode)
{
if (noexec)
{
printf ("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT",name);
if (afp == stdin)
{
int i = hdr->packed_size;
while(i--) fgetc(afp);
}
return;
}
save_quiet = quiet;
save_verbose = verbose;
if (!quiet && output_to_stdout)
{
printf ("::::::::\n%s\n::::::::\n", name);
quiet = TRUE;
verbose = FALSE;
}
else if (verify_mode)
{
quiet = FALSE;
verbose = TRUE;
}
crc = decode_lzhuf
(afp, stdout, hdr->original_size, hdr->packed_size, name, method);
quiet = save_quiet;
verbose = save_verbose;
}
else
{
if (!inquire_extract (name))
return;
if (noexec)
{
if (afp == stdin)
{
int i = hdr->packed_size;
while(i--) fgetc(afp);
}
return;
}
signal (SIGINT, interrupt);
signal (SIGHUP, interrupt);
unlink (name);
errno = 0;
remove_extracting_file_when_interrupt = TRUE;
if ((fp = open_with_make_path (name)) != NULL)
{
crc = decode_lzhuf
(afp, fp, hdr->original_size, hdr->packed_size, name, method);
fclose (fp);
}
remove_extracting_file_when_interrupt = FALSE;
signal (SIGINT, SIG_DFL);
signal (SIGHUP, SIG_DFL);
if (!fp)
return;
}
errno = 0;
if (hdr->has_crc && crc != hdr->crc)
error ("CRC error", name);
}
else if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
{
if (!ignore_directory && !verify_mode)
{
if (noexec)
{
printf ("EXTRACT %s (directory)\n", name);
return;
}
/* NAME has trailing SLASH '/', (^_^) */
if (!output_to_stdout && !make_parent_path (name))
return;
}
}
else
{
error ("Unknown information", name);
}
if (!output_to_stdout)
adjust_info (name,hdr);
}
/*----------------------------------------------------------------------*/
/* EXTRACT COMMAND MAIN */
/*----------------------------------------------------------------------*/
void
cmd_extract ()
{
LzHeader hdr;
long pos;
FILE *afp;
/* open archive file */
if ((afp = open_old_archive ()) == NULL)
fatal_error (archive_name);
if (archive_is_msdos_sfx1 (archive_name))
skip_msdos_sfx1_code (afp);
/* extract each files */
while (get_header (afp, &hdr))
{
if (need_file (hdr.name))
{
pos = ftell (afp);
extract_one (afp, &hdr);
fseek (afp, pos + hdr.packed_size, SEEK_SET);
}
else
{
if (afp != stdin)
fseek (afp, hdr.packed_size, SEEK_CUR);
else
{
int i = hdr.packed_size;
while(i--) fgetc(afp);
}
}
}
/* close archive file */
fclose (afp);
return;
}